-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix stuck soldiers leading to crashes in drawing code #1706
Open
Flamefire
wants to merge
22
commits into
Return-To-The-Roots:master
Choose a base branch
from
Flamefire:fix-soldier-crash
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Fix stuck soldiers leading to crashes in drawing code #1706
Flamefire
wants to merge
22
commits into
Return-To-The-Roots:master
from
Flamefire:fix-soldier-crash
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We usually want to browse the map anyway so just combine showing the window and revealing the map.
For debugging we often want to view a specific position. Make this easy by specifying the position as X-Y and Go-To with RETURN. TAB can be used to change between the edits which also clears the newly activated one such that new coordinates can be entered.
As we store GameObject references by pointer we must not copy them. The only exception is for soldiers where we convert a passive soldier to an attacker or defender by copying the base attributes. Mark any copy constructor we don't need as deleted and the others as explicit and protected.
In some cases we need to start at e.g. 1 not 0. Also make use of C++17 CTAD and remove the factory method.
Flamefire
force-pushed
the
fix-soldier-crash
branch
from
October 13, 2024 18:41
391cdd6
to
7d400f6
Compare
Flow86
reviewed
Oct 16, 2024
Allow to easier understand the soldier logic by translating the comments and docstrings improving the wording while doing that. Also small (mostly syntactical) changes to follow the logic more easily
Better capture meaning as it implies an action not just a search.
`CancelSeaAttack` already calls `Abrogate`
Easier to understand and validate. Also refactor one use site a bit translating the comments.
Make the decisions clearer by showing the symmetries and the few different cases.
Translate all remaining comments. Refactor code of type ``` if(arrived) { //handle arrived return } // handle not arrived ``` to ``` if(arrived) { // handle arrived } else { // handle not arrived } ``` Especially for small or similar code it emphasizes the either-or logic.
Communicate that those must not be NULL
The method is called when a free fight cannot be started not after it has ended, so reflect this in the name.
In some places we need e.g. "any water" terrain or in general a single or all descriptors matching a condition. Add `find` and `findAll` methods to the containers and add and use the explicit bool operator. Both in combination avoid using the raw `value` member of the `DescIdx` in most cases.
Also use the bool operator of `DescIdx` for invalid edge-indices.
Create 2 tests for free fights aborted by either the attacker or defender. This reproduces issue Return-To-The-Roots#1668
When one soldier involved in an upcoming free fight is waiting for the other and that aborts the free fight for any reason, e.g. when the spot becomes unreachable, the waiting soldier changes state but doesn't start moving and as he isn't moving already there is no event queued that would make it handle the new (moving) state. This leads to it being stuck there forever and also crashes the draw code which doesn't expect a supposedly walking soldier not having a walk event. Split the `AbortFreeFight` method in 2: - virtual method to determine the next state - base method to reset the free fight state for both soldiers and let them continue For the aborting soldier effectively nothing is changed. The other soldier gets a simulated walk event if he was waiting to handle the new state. As the 2 soldiers might get involved in another fight with each other both their "fight states" are cleaned up first to establish a valid state before the other soldier gets triggered.
Flamefire
force-pushed
the
fix-soldier-crash
branch
from
October 16, 2024 07:43
7d400f6
to
3782e20
Compare
rebase necessary, but other than that, lgtm |
Done. IIRC you can approve which stays active after the update/rebase such that it can be merged right away. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #1695
Fixes #1668
The cause is in both issues the same:
One soldier involved in an upcoming free fight is waiting for the other. That aborts the free fight as the spot becomes unreachable due to a removed road over water (either manually or by a captured building)
The waiting soldier changes state but doesn't start moving and as he isn't moving already there is no event queued that would make it handle the new (moving) state.
This leads to it being stuck there forever and also crashes the draw code which doesn't expect a supposedly walking soldier not having a walk-event.
Implemented solution:
Split the
AbortFreeFight
method in 2:For the aborting soldier effectively nothing is changed.
The other soldier gets a simulated walk event if he was waiting to handle the new state.
As the 2 soldiers might get involved in another fight with each other both their "fight states" are cleaned up first to establish a valid state before the other soldier gets triggered.
As this was a bit tricky to find and create a test case to reproduce this I added quite a bit refactoring:
General:
range
class start iterating not only from zero but any valueDescIdx
matching conditions (useful especially for tests to quickly find e.g. water)DescriptionVector
to have astd::vector
but indexed only byDescIdx
To understand what is happening with (fighting) soldiers I translated and fixed comments and documentation and some smaller refactoring to make it easier to read. Especially use of an enum instead of
uint8
and references where NULL isn't allowed.